/*
 * Monkey-Moore - A simple and powerful relative search tool
 * Copyright (C) 2007 Ricardo J. Ricken (Darkl0rd)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "monkey_prefs.hpp"
#include "xmlparser/xmlparser.h"

#include <wx/file.h>
#include <map>
#include <utility>
#include <vector>

using namespace std;

/**
* Fills Monkey-Moore properties with the default (factory) values.
*/
void MonkeyPrefs::setDefaultValues ()
{
   // preferences
   values[wxT("search-buffer-size")]  = wxT("4194304");
   values[wxT("preview-width")]       = wxT("30");
   values[wxT("results-offset-mode")] = wxT("hex");
   values[wxT("recent-files-size")]   = wxT("5");
   values[wxT("remember-position")]   = wxT("false");
   values[wxT("remember-size")]       = wxT("true");
   values[wxT("remember-ui-state")]   = wxT("false");

   // ui-state
   values[wxT("window-maximized")]    = wxT("false");
   values[wxT("window-centered")]     = wxT("true");
   values[wxT("window-position-x")]   = wxT("0");
   values[wxT("window-position-y")]   = wxT("0");
   values[wxT("window-size-x")]       = wxT("450");
   values[wxT("window-size-y")]       = wxT("460");
   values[wxT("open-file-path")]      = wxT("./");
   values[wxT("search-type")]         = wxT("true");
   values[wxT("wildcard")]            = wxT("*");
   values[wxT("show-all-results")]    = wxT("true");
   values[wxT("save-table-path")]     = wxT("./");
}

/**
* Loads the preferences from a proper XML file.
* @param configFile file name
* @return True on success, false on failure.
*/
bool MonkeyPrefs::load (const wxString &configFile)
{
   XMLResults pResults;
   XMLNode root = XMLNode::parseFile(configFile, wxT("config"), &pResults);

   if (pResults.error) return false;

   // preferences
   XMLNode pref = root.getChildNode(wxT("preferences"));
   values[wxT("search-buffer-size")] = pref.getChildNode(wxT("search-buffer")).getAttribute(wxT("size"));
   values[wxT("preview-width")] = pref.getChildNode(wxT("preview")).getAttribute(wxT("width"));
   values[wxT("results-offset-mode")] = pref.getChildNode(wxT("results-offset")).getAttribute(wxT("mode"));
   values[wxT("recent-files-size")] = pref.getChildNode(wxT("recent-files")).getAttribute(wxT("size"));
   values[wxT("remember-position")] = pref.getChildNode(wxT("remember-position")).getAttribute(wxT("value"));
   values[wxT("remember-size")] = pref.getChildNode(wxT("remember-size")).getAttribute(wxT("value"));
   values[wxT("remember-ui-state")] = pref.getChildNode(wxT("remember-ui-state")).getAttribute(wxT("value"));

   // ui state
   XMLNode ui_state = root.getChildNode(wxT("ui-state"));

   XMLNode w = ui_state.getChildNode(wxT("window"));
   values[wxT("window-maximized")] = w.getAttribute(wxT("maximized"));
   values[wxT("window-centered")] = w.getAttribute(wxT("centered"));

   XMLNode wpos = w.getChildNode(wxT("position"));
   values[wxT("window-position-x")] = wpos.getAttribute(wxT("x"));
   values[wxT("window-position-y")] = wpos.getAttribute(wxT("y"));

   XMLNode wsize = w.getChildNode(wxT("size"));
   values[wxT("window-size-w")] = wsize.getAttribute(wxT("w"));
   values[wxT("window-size-h")] = wsize.getAttribute(wxT("h"));

   values[wxT("search-type")] = ui_state.getChildNode(wxT("search-type")).getAttribute(wxT("value"));
   values[wxT("wildcard")] = ui_state.getChildNode(wxT("wildcard")).getAttribute(wxT("value"));
   values[wxT("advanced-shown")] = ui_state.getChildNode(wxT("advanced-shown")).getAttribute(wxT("value"));
   values[wxT("show-all-results")] = ui_state.getChildNode(wxT("show-all-results")).getAttribute(wxT("value"));

   // directories
   XMLNode dirs = root.getChildNode(wxT("directories"));
   values[wxT("open-file-path")] = dirs.getChildNode(wxT("open-file")).getAttribute(wxT("path"));
   values[wxT("save-table-path")] = dirs.getChildNode(wxT("save-table")).getAttribute(wxT("path"));

   // common charsets
   if (wxFile::Exists(wxT("charset.xml")) && wxFile::Access(wxT("charset.xml"), wxFile::read))
   {
      XMLResults r;
      XMLNode croot = XMLNode::parseFile(wxT("charset.xml"), wxT("common-charsets"), &r);

      if (!r.error)
      {
         int n_charsets = croot.nChildNode(wxT("charset"));

         for (int i = 0; i < n_charsets; i++)
         {
            XMLNode cnode = croot.getChildNode(i);

            wxString name = cnode.getAttribute(wxT("name"));
            wxString content = cnode.getText();

            common_charsets.push_back(std::make_pair(name, content));
         }
      }
   }

   return true;
}

/**
* Saves the current set of preferences into the config file.
* @param configFile file name
* @param recreate true recreates the config file
* @return True on success, false on failure.
*/
bool MonkeyPrefs::save (const wxString &configFile, bool recreate)
{
   if (recreate)
      return createConfigFile(configFile);

   XMLResults r;
   XMLNode root = XMLNode::parseFile(configFile, wxT("config"), &r);

   if (r.error)
      return false;

   // preferences
   XMLNode pref = root.getChildNode(wxT("preferences"));
   pref.getChildNodeWithAttribute(wxT("search-buffer"), wxT("size")).updateAttribute(values[wxT("search-buffer-size")]);
   pref.getChildNodeWithAttribute(wxT("results-offset"), wxT("mode")).updateAttribute(values[wxT("results-offset-mode")]);
   pref.getChildNodeWithAttribute(wxT("preview"), wxT("width")).updateAttribute(values[wxT("preview-width")]);
   pref.getChildNodeWithAttribute(wxT("recent-files"), wxT("size")).updateAttribute(values[wxT("recent-files-size")]);
   pref.getChildNodeWithAttribute(wxT("remember-position"), wxT("value")).updateAttribute(values[wxT("remember-position")]);
   pref.getChildNodeWithAttribute(wxT("remember-size"), wxT("value")).updateAttribute(values[wxT("remember-size")]);
   pref.getChildNodeWithAttribute(wxT("remember-ui-state"), wxT("value")).updateAttribute(values[wxT("remember-ui-state")]);

   // ui state
   XMLNode ui_state = root.getChildNode(wxT("ui-state"));

   XMLNode w = ui_state.getChildNode(wxT("window"));
   w.updateAttribute(values[wxT("window-maximized")], 0, wxT("maximized"));
   w.updateAttribute(values[wxT("window-centered")], 0, wxT("centered"));

   XMLNode wpos = w.getChildNode(wxT("position"));
   wpos.updateAttribute(values[wxT("window-position-x")], 0, wxT("x"));
   wpos.updateAttribute(values[wxT("window-position-y")], 0, wxT("y"));

   XMLNode wsize = w.getChildNode(wxT("size"));
   wsize.updateAttribute(values[wxT("window-size-w")], 0, wxT("w"));
   wsize.updateAttribute(values[wxT("window-size-h")], 0, wxT("h"));

   ui_state.getChildNodeWithAttribute(wxT("search-type"), wxT("value")).updateAttribute(values[wxT("search-type")]);
   ui_state.getChildNodeWithAttribute(wxT("wildcard"), wxT("value")).updateAttribute(values[wxT("wildcard")]);
   ui_state.getChildNodeWithAttribute(wxT("advanced-shown"), wxT("value")).updateAttribute(values[wxT("advanced-shown")]);
   ui_state.getChildNodeWithAttribute(wxT("show-all-results"), wxT("value")).updateAttribute(values[wxT("show-all-results")]);

   // directories
   XMLNode directories = root.getChildNode(wxT("directories"));
   directories.getChildNodeWithAttribute(wxT("open-file"), wxT("path")).updateAttribute(values[wxT("open-file-path")]);
   directories.getChildNodeWithAttribute(wxT("save-table"), wxT("path")).updateAttribute(values[wxT("save-table-path")]);

   root.writeToFile(configFile, "UTF-16", 1);
   return true;
}

/**
* Creates a brand new config file structure, filled with factory values.
* @param fileName config file name
* @return True on success, false on failure.
*/
bool MonkeyPrefs::createConfigFile (const wxString &fileName)
{
   XMLNode root = XMLNode::createXMLTopNode(wxT("config"), false);
   root.addAttribute(wxT("xmlns"), wxT("monkey-moore"));

   // preferences
   XMLNode prefs = root.addChild(wxT("preferences"));
   prefs.addChild(wxT("search-buffer")).addAttribute(wxT("size"), values[wxT("search-buffer-size")]);
   prefs.addChild(wxT("preview")).addAttribute(wxT("width"), values[wxT("preview-width")]);
   prefs.addChild(wxT("results-offset")).addAttribute(wxT("mode"), values[wxT("results-offset-mode")]);
   prefs.addChild(wxT("recent-files")).addAttribute(wxT("size"), values[wxT("recent-files-size")]);
   prefs.addChild(wxT("remember-position")).addAttribute(wxT("value"), values[wxT("remember-position")]);
   prefs.addChild(wxT("remember-size")).addAttribute(wxT("value"), values[wxT("remember-size")]);
   prefs.addChild(wxT("remember-ui-state")).addAttribute(wxT("value"), values[wxT("remember-ui-state")]);

   // ui state
   XMLNode ui_state = root.addChild(wxT("ui-state"));
   
   XMLNode window = ui_state.addChild(wxT("window"));
   window.addAttribute(wxT("maximized"), values[wxT("window-maximized")]);
   window.addAttribute(wxT("centered"), values[wxT("window-centered")]);

   XMLNode wpos = window.addChild(wxT("position"));
   wpos.addAttribute(wxT("x"), values[wxT("window-position-x")]);
   wpos.addAttribute(wxT("y"), values[wxT("window-position-y")]);

   XMLNode wsize = window.addChild(wxT("size"));
   wsize.addAttribute(wxT("w"), values[wxT("window-size-w")]);
   wsize.addAttribute(wxT("h"), values[wxT("window-size-h")]);

   ui_state.addChild(wxT("search-type")).addAttribute(wxT("value"), values[wxT("search-type")]);
   ui_state.addChild(wxT("wildcard")).addAttribute(wxT("value"), values[wxT("wildcard")]);
   ui_state.addChild(wxT("advanced-shown")).addAttribute(wxT("value"), values[wxT("advanced-shown")]);
   ui_state.addChild(wxT("show-all-results")).addAttribute(wxT("value"), values[wxT("show-all-results")]);

   // directories
   XMLNode dirs = root.addChild(wxT("directories"));
   dirs.addChild(wxT("open-file")).addAttribute(wxT("path"), values[wxT("open-file-path")]);
   dirs.addChild(wxT("save-table")).addAttribute(wxT("path"), values[wxT("save-table-path")]);

   root.writeToFile(fileName, "UTF-16", 1);
   return true;
}
